<template>
  <div class="reserve-box">
    <el-collapse
      v-model="activeName"
      accordion
    >
      <el-collapse-item
        v-for="pro in reserveProjectList"
        :key="pro.id"
        :title="pro.name"
        :name="pro.id"
      >
        <template #title>
          <div class="project-name">
            <el-icon>
              <ele-Calendar />
            </el-icon>
            {{ pro.name }}
          </div>
        </template>
        <el-calendar
          v-model="dateValues[pro.id]"
          @input="val => handleSelect(pro.id, val)"
          :class="`reserve-calendar${activeName}`"
        >
          <template #date-cell="{ data }">
            <div :class="[disabledDate(data.day) ? 'disable-date' : '']">
              <p
                :class="data.isSelected ? 'is-selected' : ''"
                class="reserve-calendar-date"
              >
                {{ isMobileTag ? data.day.split("-")[2] : data.day.split("-").slice(1).join("-") }}
              </p>
              <p class="text">
                {{ calcQuotaWeek(pro, data.day) }}
              </p>
            </div>
          </template>
        </el-calendar>
        <el-alert
          v-if="dateValues[pro.id]"
          :title="`已选：${formatReserveDate(pro.id)}`"
          type="success"
          class="select-date-alert"
          @close="handleCancelSelect(pro.id)"
        />
      </el-collapse-item>
    </el-collapse>
  </div>
</template>

<script setup lang="ts" name="TReserve">
import { ref, watch, onMounted, nextTick, useAttrs, PropType, inject, Ref } from "vue";
import { getRequest } from "@/api/baseRequest";
import { useRoute } from "vue-router";
import dayjs from "dayjs";
import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js";
import isSameOrBefore from "dayjs/plugin/isSameOrBefore.js";
import { isMobile } from "@/utils/other";
import { IS_MOBILE_TAG_KEY } from "@/views/formgen/components/GenerateForm/types/constants";

dayjs.extend(isSameOrAfter);
dayjs.extend(isSameOrBefore);

type ReserveConfig = {
  id: number; // 配置 ID
  name: string; // 配置名称
  quotaWeek: Record<number, any>; // 每周预约名额
  reserveDateRangeType: 1 | 2; // 预约时间范围类型：1 - 长期预约, 2 - 限时预约
  reserveDateRange: string[]; // 预约时间范围（如日期字符串的数组）
  openWeekDays: number[]; // 开放预约的星期几（0 - 周日, 1 - 周一, ..., 6 - 周六）
  // 提前几天预约
  reserveBeforeDay?: number;
  // 只能预约几天内
  reserveAfterDay?: number;
};

const props = defineProps({
  reserveProjectList: {
    type: Array as PropType<ReserveConfig[]>,
    default: () => {
      return [];
    }
  },
  value: {
    type: Object,
    default: () => {
      return {};
    }
  }
});

const emit = defineEmits(["update:value"]);
const isMobileTag = inject<Ref<boolean>>(IS_MOBILE_TAG_KEY, ref(isMobile()));

// Reactive state
const activeName = ref<number>(1);
const dateValues = ref<Record<string, Date | null>>({});
const dateReserveCount = ref<Record<string, number>>({});

const attrs = useAttrs();

const formatReserveDate = (id: string) => {
  if (!dateValues.value[id]) {
    return "";
  }
  return dayjs(dateValues.value[id] as Date).format("YYYY-MM-DD");
};

const key = useRoute().params.key;

const changeDate = (dayStr: string) => {
  //日期增加30天
  //日期增加30天  .replace(/-/g, '/') 解决IOS浏览器不支2012-10-22 这种格式
  const date = dayjs(dayStr, "YYYY-MM-DD");
  console.log(date);
  const startDate = date.subtract(35, "day");
  const endDate = date.add(35, "day");

  getRequest("/form/ext/getReservationCount", {
    formKey: key,
    formItemId: attrs.dId,
    projectId: activeName.value,
    startDate: startDate.format("YYYY-MM-DD"),
    endDate: endDate.format("YYYY-MM-DD")
  }).then(res => {
    dateReserveCount.value = res.data;
  });
};

// Watchers
watch(
  dateValues,
  newValue => {
    const formattedValues = Object.keys(newValue).reduce<Record<string, string>>((pre, cur) => {
      if (newValue[cur]) {
        pre[cur] = dayjs(newValue[cur] as Date).format("YYYY-MM-DD");
      }
      return pre;
    }, {});
    emit("update:value", formattedValues);
  },
  { deep: true }
);

watch(
  activeName,
  () => {
    // 如果没有选择的
    if (!dateValues.value[activeName.value]) {
      changeDate(dayjs().format("YYYY-MM-DD"));
    }
  },
  { immediate: true, deep: true }
);

// Lifecycle hook
onMounted(() => {
  const value = props.value || {};
  console.log(value);
  for (const key of Object.keys(value)) {
    dateValues.value[key] = dayjs(value[key], "YYYY-MM-DD").toDate();
  }
  if (props.reserveProjectList && props.reserveProjectList.length) {
    activeName.value = props.reserveProjectList[0].id;
  }
});

// Methods
const handleSelect = (proId: string, val: Date) => {
  if (disabledDate(dayjs(val).format("YYYY-MM-DD")) || dayjs(val).isBefore(dayjs().startOf("day"))) {
    nextTick(() => handleCancelSelect(proId));
  }
};

const handleCancelSelect = (id: string) => {
  dateValues.value[id] = null;
};

const calcQuotaWeek = (project: any, day: string): string => {
  const date = dayjs(day, "YYYY-MM-DD");
  // 小于今天
  if (date.isBefore(dayjs(), "day")) {
    return "";
  }
  if (project.quotaWeek[date.day()]) {
    const count = dateReserveCount.value[day] || 0;
    return "余" + (project.quotaWeek[date.day()] - count);
  }
  return "充足";
};

/**
 * 是否禁用当前日期
 * @param dayStr 日期字符串
 * @return  true表示禁用日期  false表示不禁用
 */
const disabledDate = (dayStr: string): boolean => {
  const project = props.reserveProjectList.find(item => item.id === activeName.value);
  if (!project) return false;

  let reserveDateRange: string[] = [];
  // 当前开放的日期范围
  if (project.reserveDateRangeType && project.reserveDateRangeType == 2) {
    reserveDateRange = project.reserveDateRange || [];
  }
  // 开放的每周周几
  const openWeekDays = project.openWeekDays;
  const date = dayjs(dayStr, "YYYY-MM-DD");

  // 先判断下是否在开放的预约时间段
  if (
    project.reserveDateRangeType == 2 &&
    reserveDateRange.length === 2 &&
    (date.isBefore(dayjs(reserveDateRange[0], "YYYY-MM-DD"), "day") ||
      date.isAfter(dayjs(reserveDateRange[1], "YYYY-MM-DD"), "day"))
  ) {
    return true;
  }
  // 再判断下是否在开放的每周周几
  const allowWeekDay = openWeekDays.length > 0 && !openWeekDays.includes(date.day());
  if (allowWeekDay) {
    return allowWeekDay;
  }
  //是否开启提前预约
  if (project.reserveBeforeDay && project.reserveAfterDay) {
    const reserveBeforeDay = project.reserveBeforeDay;
    const reserveAfterDay = project.reserveAfterDay;
    const startDate = dayjs().add(reserveBeforeDay, "day");
    const endDate = dayjs().add(reserveBeforeDay + reserveAfterDay - 1, "day");
    console.log(endDate);
    if (date.isBefore(startDate, "day") || date.isAfter(endDate, "day")) {
      return true;
    }
  }
  return false;
};
</script>
<style lang="scss" scoped>
.reserve-box .project-name {
  padding-left: 20px;
  font-weight: bold;
}

.reserve-box .text {
  font-size: 0.6rem;
  margin-top: 0;
  font-weight: normal;
  color: var(--form-theme-color);
}

.disable-date {
  color: #ccc;
  cursor: none;

  .text {
    color: #ccc;
  }
}

:deep(.reserve-box .el-calendar-day) {
  height: 50px !important;
  text-align: center !important;
}

:deep(.reserve-box .el-calendar-table .is-selected .el-calendar-day:hover) {
  background-color: var(--form-theme-color);
  color: #fff;
}

:deep(.reserve-box .el-calendar-table td.is-selected) {
  background-color: var(--form-theme-color);
  color: #fff;

  .text {
    color: #fff;
  }
}

:deep(.el-calendar) {
  --el-calendar-cell-width: 55px;
}

@media screen and (max-width: 500px) {
  :deep(.el-calendar__body) {
    padding: 0px 0px 0px;
  }
  :deep(.el-calendar) {
    --el-calendar-cell-width: 85px;
  }
  :deep(.el-calendar-table .el-calendar-day) {
    box-sizing: border-box;
    padding: 4px 2px;
    height: 50px !important;
  }
  :deep(.reserve-box .el-calendar-day) {
    height: 50px !important;
    padding: 0 !important;
    text-align: center !important;
  }
  .reserve-calendar-date {
    text-align: center !important;
  }

  .reserve-box .text {
    text-align: center !important;
  }

  .select-date-alert {
    margin-top: 10px;
  }
}
</style>
